/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package app.net.server;

import app.game.GlobalStatics;
import app.net.Client;
import app.net.messages.IdMessage;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * wait for clients to connect and initalize threads
 *
 * @author skyr
 */
public class ServerApp {

    private ServerSocket server;
    private boolean waitingConnections = true;
    private ServerSyncThread serverSyncThread;
    private ServerGameLoop serverGameLoop;

    public void init() {
        initializeSockets();
        initializeGameLoop();
        initializeSyncThread();
    }

    public void start() {
        while (waitingConnections) {
            try {
                System.out.println("waiting connection ...");
                Socket s = server.accept();
                /*
                 *  receive new connection calculate and id and send it
                 */
                int id = serverGameLoop.getClientsList().size() + 1;
                Client client = new Client("player " + id, id, s);
                serverGameLoop.getClientsList().add(client);
                System.out.println("Client " + id + " connected: " + s);
                ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
                serverSyncThread.setOutputStream(id, oos);
                IdMessage idMessage = new IdMessage();
                idMessage.setId(id);
                oos.writeObject(idMessage);
                oos.flush();
                
                /*
                 * a new thread for each client to receive its input
                 */
                initializeReceiveThread(client);

            } catch (IOException ex) {
                Logger.getLogger(ServerApp.class.getName()).log(Level.SEVERE, "connection fail", ex);
            }
        }
    }

    public void stop() {
        serverGameLoop.stop();
        serverSyncThread.stop();
        waitingConnections = false;
        try {
            server.close();
        } catch (IOException ex) {
            Logger.getLogger(ServerApp.class.getName()).log(Level.SEVERE, "server close fail", ex);
        }
    }

    private void initializeSockets() {
        try {
            System.out.println("Binding to port " + GlobalStatics.port + ", please wait  ...");
            server = new ServerSocket(GlobalStatics.port);
            System.out.println("Server started: " + server);
        } catch (IOException ex) {
            Logger.getLogger(ServerApp.class.getName()).log(Level.SEVERE, "server start fail", ex);
        }
    }

    private void initializeSyncThread() {
        serverSyncThread = new ServerSyncThread(serverGameLoop);
        serverSyncThread.start();
    }

    private void initializeGameLoop() {
        serverGameLoop = new ServerGameLoop();
        serverGameLoop.start();
    }

    private void initializeReceiveThread(Client client) {
        ServerReceiveThread receiveThread = new ServerReceiveThread(client, serverGameLoop);
        receiveThread.start();
    }

    public static void main(String[] args) {
        ServerApp app = new ServerApp();
        app.init();
        app.start();
    }
}
